#./myvenv/bin/python3
# coding="utf-8"

import requests
import re
import json
import time
import random
# 解决验证码问题，经过测试实际使用过程中不会出验证码，所以没装的话可以屏蔽掉
import pytesseract
#from PIL import Image
from PIL import Image
from io import BytesIO
import ssl;
'''
初次使用时，请先从浏览器的开发者工具中获取百度网盘的Cookie，并设置在init方法中进行配置，并调用verifyCookie方法测试Cookie的有效性
已实现的方法：
1.获取登录Cookie有效性；
2.获取网盘中指定目录的文件列表；
3.获取加密分享链接的提取码；
4.转存分享的资源；
5.重命名网盘中指定的文件；
6.删除网盘中的指定文件；
7.移动网盘中指定文件至指定目录；
8.创建分享链接；
'''
# 定义一个函数来提取指定键的值
def find_value(json_str, key):
    # 构造键名
    key_str = key

    # 查找键名的位置
    start_index = json_str.find(key_str)
    if start_index == -1:
        return None

    # 确定值的起始位置和结束位置
    value_start_index = start_index + len(key_str)
    value_end_index = json_str.find(',', value_start_index)
    if value_end_index == -1:
        value_end_index = json_str.find('}', value_start_index)
    if value_end_index == -1:
        return None

    # 提取值并去除首尾空格和双引号
    value = json_str[value_start_index:value_end_index].strip().strip('"')
    value = value.replace("\"","")
    return value

class BaiDuPan(object):	
	def __init__(self):
		# 创建session并设置初始登录Cookie
		self.session = requests.session()
		#genghao
		#self.session.cookies['BDUSS'] = 'h3VjR2STkyTmZZQnllNzU3bVJyYX4ydTRnQ1NXb0kzR0xOdTFXVFF3ZUYtLU5tRVFBQUFBJCQAAAAAAAAAAAEAAABt-BYAZ2VuZ2hhb2xvdmUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIVuvGaFbrxmc2'
		
		#hudan
		self.session.cookies['BDUSS'] = 'Wp4d3hJdU5VeG5vbG4yfkhTU2U4S0xyc2lBYXdER3RnflZ5R3g5WGlSWEpJZVJtRUFBQUFBJCQAAAAAAAAAAAEAAABn49Zx1bez4fN773kAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMmUvGbJlLxmO'
		
		#genghao
		#self.session.cookies['STOKEN'] = '7f43e3e6d2a1e630148c54070a7e8cfe4a3a7279596c17c1b68bf0af94ae8ba5'
		self.session.cookies['STOKEN'] = '681ce21adad39379bb1c937e16d0e60dce7e7da5e9b42653dd5183d8cad4ed28'

		self.bdstoken = 'f5a0a3de2dea6d2ce7acef3b93eae77e'
		# self.session.cookies['BDUSS'] = ''
		# self.session.cookies['STOKEN'] = ''
		self.logid = 'QjkzNTEwOUFGOEQzQTA5MjIwMUU1MzBFNzRFNUJERjE6U0w9MDpOUj0xMDpGRz0x';
		self.dp_logid = '64033300352906050034';
						 #57550800259747070034
		self.headers = {
			'Host': 'pan.baidu.com',
			'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
		}
		#self.seKey = 'zV91wcY9FzMwmljc5tOlHoHgDsl3nC4b0%2FqLaW2rQRo%3D';
		self.seKey = 'zV91wcY9FzMwmljc5tOlHoHgDsl3nC4b0%2FqLaW2rQRo%3D'#kC5ZOeoHjgRBBB%2BjgEiYLz52SugzvocP299vqdP06JI%3D

	'''
	验证Cookie是否已登录
	返回值errno代表的意思：
	0 有效的Cookie；1 init方法中未配置登录Cookie；2 无效的Cookie
	'''
	def verifyCookie(self):
		if(self.session.cookies['BDUSS'] == '' or self.session.cookies['STOKEN'] == ''):
			return {'errno': 1, 'err_msg': '请在init方法中配置百度网盘登录Cookie'}
		else:
			response = self.session.get('https://pan.baidu.com/', headers=self.headers)
			home_page = response.content.decode("utf-8")
			#print(home_page)
			if('<title>百度网盘</title>' in home_page):
				#user_name = re.findall(r'initPrefetch\((.+?)\'\)', home_page)[0]
				#user_name = re.findall(r'\, \'(.+?)\'\)', home_page)[0]
				#user_name = re.findall(r'useranme\((.+?)\'\)', home_page)[0]
				#print(locals['userInfo']['username'])
				#return {'errno': 0, 'err_msg': '有效的Cookie，用户名：%s' % locals['userInfo']['username']}
				pattern = r'window.locals = {.*?"icon":'
				match = re.search(pattern, home_page)[0]
				if match:
					#print(type(match))
					#print(match)
					# 查找 username 的位置
					username_index = match.find('"username":"')
					if username_index != -1:
					    # 利用切片找到 username 的值
					    username_start = username_index + len('"username":"')
					    username_end = match.find('"', username_start)
					    username = match[username_start:username_end]
					else:
					    username = None

					# 查找 bdstoken 的位置
					bdstoken_index = match.find('"bdstoken":"')
					if bdstoken_index != -1:
					    # 利用切片找到 bdstoken 的值
					    bdstoken_start = bdstoken_index + len('"bdstoken":"')
					    bdstoken_end = match.find('"', bdstoken_start)
					    bdstoken = match[bdstoken_start:bdstoken_end]
					else:
					    bdstoken = None

					# 打印提取到的值
					print("Username:", username)
					print("Bdstoken:", bdstoken)
				else:
					print("未找到匹配")
			else:
				return {'errno': 2, 'err_msg': '无效的Cookie！'}
			return {'errno': 0, 'err_msg': 'Cookie ok！'}

	
	'''
	获取指定目录的文件列表，直接返回原始的json
	'''
	def getFileList(self, dir='/202408/', order='time', desc=0, page=1, num=5000):
		'''
		构造获取文件列表的URL：
		https://pan.baidu.com/api/list?
		bdstoken=  从首页中可以获取到
		&dir=/  需要获取的目录
		&order=name  可能值：name，time，size
		&desc=0  0表示正序，1表示倒序
		&page=  第几页
		&num=100  每页文件数量
		&t=0.8685513844705777  推测为随机字符串
		&startLogTime=1581862647373  时间戳
		&logid=MTU4MTg2MjY0NzM3MzAuMzM2MTAzMzk5MTg3NzYyOQ==  固定值
		&clienttype=0  固定值
		&showempty=0  固定值
		&web=1  固定值
		&channel=chunlei  固定值
		&app_id=250528  固定值
		'''
		# 访问首页获取bdstoken 
		response = self.session.get('https://pan.baidu.com/', headers=self.headers)
		#print("response:",response);
		bdstoken = self.bdstoken;#re.findall(r'initPrefetch\(\'(.+?)\'\,', response.content.decode("utf-8"))[0]
		t = random.random()
		startLogTime = str(int(time.time()) * 1000)
		url = 'https://pan.baidu.com/api/list?bdstoken=%s&dir=%s&order=%s&desc=%s&page=%s&num=%s&t=%s&startLogTime=%s\
				&logid=%s&clienttype=0&showempty=0&web=1&channel=chunlei&app_id=250528'\
				% (bdstoken, dir, order, desc, page, num, t, startLogTime,self.logid)
		#print("url:",url);
		headers = self.headers
		headers['Referer'] = 'https://pan.baidu.com/disk/home?'
		response = self.session.get(url, headers=headers)
		print("response 222:",response);
		#print(response.json())
		return response.json()


	'''
	获取分享链接的提取码
	返回值errno代表的意思：
	0 提取码获取成功；1 提取码获取失败；
	'''
	@staticmethod
	def getSharePwd(surl):
		# 云盘精灵的接口
		ypsuperkey_headers = {
			'Host': 'ypsuperkey.meek.com.cn',
			'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
		}
		response = requests.get('https://ypsuperkey.meek.com.cn/api/v1/items/BDY-%s?client_version=2019.2' % surl, headers=ypsuperkey_headers)
		pwd = response.json().get('access_code', '')
		if(not pwd):
			# 小鸟云盘搜索接口
			aisou_headers = {
				'Host': 'helper.aisouziyuan.com',
				'Origin': 'https://pan.baidu.com',
				'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
				'Referer': 'https://pan.baidu.com/share/init?surl=%s' % surl,
			}
			form_data = {
				'url': surl,
				'wrong': 'false',
				'type': 'baidu',
				'v': '3.132',
			}
			response = requests.post('https://helper.aisouziyuan.com/Extensions/Api/ResourcesCode?v=3.132', headers=aisou_headers, data=form_data)
			pwd = response.text
		errno, err_msg = (0, '提取码获取成功') if pwd else (1, '提取码获取失败：%s' % response.text)
		return {'errno': errno, 'err_msg': err_msg, 'pwd': pwd}


	'''
	识别 验证加密分享时的验证码
	返回值errno代表的意思：
	0 识别成功；1 识别失败；其他值 获取验证码失败；
	'''
	def vcodeOCR(self):
		# 获取验证码
		vcode_res = requests.get('https://pan.baidu.com/api/getcaptcha?prod=shareverify&web=1&channel=chunlei&web=1&app_id=250528&bdstoken=%s&clienttype=0' % self.bdstoken, headers=self.headers)
		vcode_json = vcode_res.json()
		print("vcodeOCR vcode_json:",vcode_json)
		if(vcode_json['errno'] == 0):
			# 获取验证码图片
			genimage = requests.get(vcode_json['vcode_img'], headers=self.headers)
			#print("genimage.content:",genimage.content)
			#非自动化脚本，可以改为人工识别，并且将人工识别的验证码保存，用于后续的CNN训练
			# vcode_image = BytesIO(genimage.content)
			# image = Image.open(vcode_image)	
			# image.show()
			# vcode = input('请输入验证码：')
			# f = open('./vcodeImg/%s - %s.jpg' % (vcode, str(int(time.time()) * 1000)), 'wb')
			# f.write(genimage.content)
			# f.close()

			'''
			将验证码图片加载至内存中进行自动识别
			由于验证码旋转和紧贴，所以导致pytesseract识别率非常底！
			考虑基于CNN深度学习识别，筹备数据集需要一定的时间
			临时解决方案是：识别失败进行重试，加大重试次数
			'''
			vcode_image = BytesIO(genimage.content)
			image = Image.open(vcode_image)		
			pytesseract.pytesseract.tesseract_cmd = r"full path to the exe file"
			pytesseract.pytesseract.tesseract_cmd = "C:\\Program Files (x86)\\Tesseract-OCR\\tesseract.exe"		
			print("pytesseract.pytesseract.tesseract_cmd:",pytesseract.pytesseract.tesseract_cmd)
			vcode = pytesseract.image_to_string(image,config='--psm 11')
			print("vcode is:",vcode)
			errno, err_msg = (1, '识别失败') if(len(vcode) != 4) else (0, '识别成功')
			vcode_str = vcode_json['vcode_str']
		else:
			errno = vcode_json['errno']
			err_msg = '获取验证码失败'
			vcode_str = ''
		return {'errno': errno, 'err_msg': err_msg, 'vcode': vcode, 'vcode_str': vcode_str}


	'''
	验证加密分享
	返回值errno代表的意思：
	0 加密分享验证通过；1 验证码获取失败；2 提取码不正确；3 加密分享验证失败；4 重试几次后，验证码依旧不正确；
	'''
	def verifyShare(self, surl, bdstoken, pwd, referer):
		'''
		构造密码验证的URL：https://pan.baidu.com/share/verify?
		surl=62yUYonIFdKGdAaueOkyaQ  从重定向后的URL中获取
		&t=1572356417593  时间戳
		&channel=chunlei  固定值
		&web=1  固定值
		&app_id=250528  固定值
		&bdstoken=742aa0d6886423a5503bbc67afdb2a7d  从重定向后的页面中可以找到，有时候会为空，经过验证，不要此字段也可以
		&logid=MTU0ODU4MzUxMTgwNjAuNDg5NDkyMzg5NzAyMzY1MQ==  不知道什么作用，暂时为空或者固定值都可以
		&clienttype=0  固定值
		'''
		t = str(int(time.time()) * 1000)
		url = 'https://pan.baidu.com/share/verify?surl=%s&t=%s&channel=chunlei&web=1&app_id=250528&bdstoken=%s&logid=%s&clienttype=0' % (surl, t, self.bdstoken,self.logid)
		form_data = {
			'pwd': pwd,
			'vcode': '',
			'vcode_str': '',
		}
		print("verifyShare url",url)
		# 设置重试机制
		is_vcode = False
		for n in range(1, 5):
			# 自动获取并识别验证码，使用pytesseract自动识别时，可加大重试次数
			if is_vcode:
				ocr_result = self.vcodeOCR()
				if(ocr_result['errno'] == 0):
					form_data['vcode'] = ocr_result['vcode']
					form_data['vcode_str'] = ocr_result['vcode_str']
				elif(ocr_result['errno'] == 1):
					continue
				else:
					return {'errno': 1, 'err_msg': '验证码获取失败：%d' % ocr_result['errno']}
			headers = self.headers
			headers['referer'] = referer
			#print("url:",url)
			#print("headers:",headers)
			#print("form_data:",form_data)
			# verify_json['errno']：-9表示提取码不正确；-62表示需要验证码/验证码不正确（不输入验证码也是此返回值）
			verify_res = self.session.post(url, headers=headers, data=form_data)
			verify_json = verify_res.json()
			print("verify_json:",verify_json)
			if(verify_json['errno'] == 0):
				return {'errno': 0, 'err_msg': '加密分享验证通过'}
			elif(verify_json['errno'] == -9):
				return {'errno': 2, 'err_msg': '提取码不正确'}
			elif(verify_json['errno'] == -62):
				is_vcode = True
			else:
				return {'errno': 3, 'err_msg': '加密分享验证失败：%d' % verify_json['errno']}
		return {'errno': 4, 'err_msg': '重试多次后，验证码依旧不正确：%d' % (verify_json['errno'] if("verify_json" in locals()) else -1)}


	'''
	返回值errno代表的意思：
	0 转存成功；1 无效的分享链接；2 分享文件已被删除；
	3 分享文件已被取消；4 分享内容侵权，无法访问；5 找不到文件；6 分享文件已过期
	7 获取提取码失败；8 获取加密cookie失败； 9 转存失败；
	'''
	def saveShare(self, url, pwd=None, path='/'):
		share_res = self.session.get(url, headers=self.headers)
		print("share_res:",share_res)
		share_page = share_res.content.decode("utf-8")
		#print("share_page:",share_page)
		'''
		1.如果分享链接有密码，会被重定向至输入密码的页面；
		2.如果分享链接不存在，会被重定向至404页面https://pan.baidu.com/error/404.html，但是状态码是200；
		3.如果分享链接已被删除，页面会提示：啊哦，你来晚了，分享的文件已经被删除了，下次要早点哟。
		4.如果分享链接已被取消，页面会提示：啊哦，你来晚了，分享的文件已经被取消了，下次要早点哟。
		5.如果分享链接涉及侵权，页面会提示：此链接分享内容可能因为涉及侵权、色情、反动、低俗等信息，无法访问！
		6.啊哦！链接错误没找到文件，请打开正确的分享链接!
		7.啊哦，来晚了，该分享文件已过期
		'''
		if('error/404.html' in share_res.url):
			return {"errno": 1, "err_msg": "无效的分享链接", "extra": "", "info": ""},"error1"
		if('你来晚了，分享的文件已经被删除了，下次要早点哟' in share_page):
			return {"errno": 2, "err_msg": "分享文件已被删除", "extra": "", "info": ""},"error2"
		if('你来晚了，分享的文件已经被取消了，下次要早点哟' in share_page):
			return {"errno": 3, "err_msg": "分享文件已被取消", "extra": "", "info": ""},"error3"
		if('此链接分享内容可能因为涉及侵权、色情、反动、低俗等信息，无法访问' in share_page):
			return {"errno": 4, "err_msg": "分享内容侵权，无法访问", "extra": "", "info": ""},"error4"
		if('链接错误没找到文件，请打开正确的分享链接' in share_page):
			return {"errno": 5, "err_msg": "链接错误没找到文件", "extra": "", "info": ""},"error5"
		if('啊哦，来晚了，该分享文件已过期' in share_page):
			return {"errno": 6, "err_msg": "分享文件已过期", "extra": "", "info": ""},"error6"
		if('啊哦，你所访问的页面不存在了' in share_page):
			return {"errno": 6, "err_msg": "你所访问的页面不存在了", "extra": "", "info": ""},"error66"
		# 提取码校验的请求中有此参数
		bdstoken = self.bdstoken;#re.findall(r'bdstoken\":\"(.+?)\"', share_page)
		#bdstoken = bdstoken[0] if(bdstoken) else ''
		# 如果加密分享，需要验证提取码，带上验证通过的Cookie再请求分享链接，即可获取分享文件
		print("share_res.url",share_res.url)
		if('init' in share_res.url):
			surl = re.findall(r'surl=(.+?)$', share_res.url)[0]
			print("surl:",surl)
			if(pwd == None):
				pwd_result = self.getSharePwd(surl)
				if(pwd_result['errno'] != 0):
					return {"errno": 7, "err_msg": pwd_result['err_msg'], "extra": "", "info": ""},"error81";
				else:
					pwd = pwd_result['pwd']
			referer = share_res.url
			print("referer:",referer)
			verify_result = self.verifyShare(surl, bdstoken, pwd, referer)
			print("verify_result:",verify_result)
			if(verify_result['errno'] != 0):
				return {"errno": 8, "err_msg": verify_result['err_msg'], "extra": "", "info": ""},"error88"
			else:
			# 加密分享验证通过后，使用全局session刷新页面（全局session中带有解密的Cookie）
				share_res = self.session.get(url, headers=self.headers)
				print("share_res:",share_res)
				share_page = share_res.content.decode("utf-8")
				#print("share_page:",share_page)
		# 更新bdstoken，有时候会出现 AttributeError: 'NoneType' object has no attribute 'group'，重试几次就好了
		#print("xxxx:",re.search("window.yunData=(({.*}))", share_page))
		match = re.search(r"window\.yunData=(\{.*?\});", share_page,re.DOTALL);
		#print("match:",match)
		if match == None:
			return {'errno': "error1", 'err_msg': "json is null", "extra": "", "info": ""},"error8";
		json_str = match.group(1);
		#print("match group:",json_str)
		json_str = json_str.replace("'","\"")
		json_str = json_str.replace("1,","\"1\",")
		print("new json_str:",json_str)
		#print("new json_str:",type(json_str))
		#share_data = json.loads(json_str)
		#print("share_data:",share_data)
		# bdstoken_match = re.search(r'"bdstoken":\s*"([^"]+)"', json_str)
		# share_uk_match = re.search(r'"share_uk":\s*"([^"]+)"', json_str)
		# shareid_match = re.search(r'"shareid":\s*"([^"]+)"', json_str)
		bdstoken_value = ''
		share_uk_value = ''
		shareid_value = ''
		# if bdstoken_match:
		#     bdstoken_value = bdstoken_match.group(1)
		#     print("bdstoken:", bdstoken_value)

		# if share_uk_match:
		#     share_uk_value = share_uk_match.group(1)
		#     print("share_uk:", share_uk_value)

		# if shareid_match:
		#     shareid_value = shareid_match.group(1)
		#     print("shareid:", shareid_value)

		#share_data = json.loads(re.search(r"window.yunData=\(({.*})\)", share_page).group(1))
		# bdstoken = share_data['bdstoken']
		# shareid = share_data['shareid']
		# _from = share_data['uk']
		# 调用函数来获取 bdstoken、share_uk 和 shareid 的值
		bdstoken_value = find_value(json_str, "bdstoken")
		share_uk_value = find_value(json_str, "share_uk")
		shareid_value = find_value(json_str, "shareid")

		# 打印结果
		print("bdstoken:", bdstoken_value)
		print("share_uk:", share_uk_value)
		print("shareid:", shareid_value)
		bdstoken = bdstoken_value.replace(":","")
		shareid = shareid_value.replace(":","")
		_from = share_uk_value.replace(":","")
		'''
		构造转存的URL，除了logid不知道有什么用，但是经过验证，固定值没问题，其他变化的值均可在验证通过的页面获取到
		'''
		#seKey=iSt1cf%2FQwIeizc%2FtmAveNmBQjIQjy6euVICA1TpdZgA%3D
			  #iSt1cf/QwIeizc/tmAveNmBQjIQjy6euVICA1TpdZgA=
		#HttpResult result = http.GetHtml(itemhttp);
		#MatchCollection ShopNos = Regex.Matches(result.Html, @"randsk"":""([\s\S]*?)""");
		#sekey = ShopNos[0].Groups[1].Value;
		#dp-logid=71613500898142600035
		#save_url = 'https://pan.baidu.com/share/transfer?shareid=%s&seKey=%s&from=%s&ondup=newcopy&async=1&channel=chunlei&web=1&app_id=250528&bdstoken=%s&logid=%s&clienttype=0&dp-logid=%s' % (shareid, self.seKey,_from, bdstoken,self.logid,self.dp_logid)
		#NUQ0RTQwOTIzQzc3MkE0RDhEMEFEMTEyNjczMzJEODU6U0w9MDpOUj0xMDpGRz0x
		save_url = 'https://pan.baidu.com/share/transfer?shareid=%s&from=%s&seKey=%s&channel=chunlei&web=1&app_id=250528&bdstoken=%s&logid=%s&clienttype=0&dp-logid=%s' % (shareid, _from,self.seKey, bdstoken,self.logid,self.dp_logid)

		print("save_url:",save_url)
		#print("share_page:",share_page)
		match2 = re.search(r'"file_list":\s*\[(.*?)\]\,', share_page)
		if match2 == None:
			return {'errno': "error1", 'err_msg': "json is null", "extra": "", "info": ""},"error71"
		print("match2:",match2)
		json_str2 = match2.group(1);
		print("json_str2:",json_str2)
		if(json_str2 == "" ):
			return {'errno': "error1", 'err_msg': "json is null", "extra": "", "info": ""},"error7"
		jsonData = json.loads(json_str2);
		print("jsonData:",jsonData)
		#file_list = share_data['file_list']['list']
		form_data = {
			# 这个参数一定要注意，不能使用['fs_id', 'fs_id']，谨记！for item in file_list
			'fsidlist': '[' + str(jsonData['fs_id']) + ']',
			'path': path#,
			 # 'type': 1
		}
		print("form_data",form_data)
		headers = self.headers
		headers['Origin'] = 'https://pan.baidu.com'
		headers['referer'] = url
		'''
		用带登录Cookie的全局session请求转存
		如果有同名文件，保存的时候会自动重命名：类似xxx(1)
		暂时不支持超过文件数量的文件保存
		'''
		save_res = self.session.post(save_url, headers=headers, data=form_data)
		print("save_res:",save_res)
		save_json = save_res.json()
		print("save_json:",save_json)
		errno, err_msg, extra, info = (0, '转存成功', save_json['extra'], save_json['info']) if(save_json['errno'] == 0) else (9, '转存失败：%d' % save_json['errno'], '', '')
		return {'errno': errno, 'err_msg': err_msg, "extra": extra, "info": info},str(jsonData['fs_id'])


	'''
	重命名指定文件
	0 重命名成功；1 重命名失败；
	'''
	def rename(self, path, newname):
		'''
		构造重命名的URL：https://pan.baidu.com/api/filemanager?
		bdstoken=  从首页可以获取到
		&opera=rename  固定值
		&async=2  固定值
		&onnest=fail  固定值
		&channel=chunlei  固定在
		&web=1  固定值
		&app_id=250528  固定值
		&logid=MTU4MTk0MzY0MTQwNzAuNDA0MzQxOTM0MzE2MzM4Ng==  固定值
		&clienttype=0  固定值
		'''
		response = self.session.get('https://pan.baidu.com/', headers=self.headers)
		bdstoken = re.findall(r'initPrefetch\(\'(.+?)\'\,', response.content.decode("utf-8"))[0]
		url = 'https://pan.baidu.com/api/filemanager?bdstoken=%s&opera=rename&async=2&onnest=fail&channel=chunlei&web=1&app_id=250528\
				&logid=MTU0ODU4MzUxMTgwNjAuNDg5NDkyMzg5NzAyMzY1MQ==&clienttype=0' % bdstoken
		form_data = {"filelist": "[{\"path\":\"%s\",\"newname\":\"%s\"}]" % (path, newname)}
		response = self.session.post(url, headers=self.headers, data=form_data)
		if(response.json()['errno'] == 0):
			return {'errno': 0, 'err_msg': '重命名成功！'}
		else:
			return {'errno': 1, 'err_msg': '重命名失败！', 'info': response.json()}



	'''
	删除指定文件
	0 删除成功；1 删除失败；
	'''
	def delete(self, path):
		'''
		构造重命名的URL：https://pan.baidu.com/api/filemanager?
		bdstoken=  从首页可以获取到
		&opera=delete  固定值
		&async=2  固定值
		&onnest=fail  固定值
		&channel=chunlei  固定在
		&web=1  固定值
		&app_id=250528  固定值
		&logid=MTU4MTk0MzY0MTQwNzAuNDA0MzQxOTM0MzE2MzM4Ng==  固定值
		&clienttype=0  固定值
		'''
		#print("delete path:",path)
		response = self.session.get('https://pan.baidu.com/', headers=self.headers)
		bdstoken = self.bdstoken;#re.findall(r'initPrefetch\(\'(.+?)\'\,', response.content.decode("utf-8"))[0]
		url = 'https://pan.baidu.com/api/filemanager?bdstoken=%s&opera=delete&async=2&onnest=fail&channel=chunlei&web=1&app_id=250528\
				&logid=MTU0ODU4MzUxMTgwNjAuNDg5NDkyMzg5NzAyMzY1MQ==&clienttype=0' % bdstoken
		form_data = {"filelist": "[\"%s\"]" % path}
		response = self.session.post(url, headers=self.headers, data=form_data)
		if(response.json()['errno'] == 0):
			return {'errno': 0, 'err_msg': '删除成功！'}
		else:
			return {'errno': 1, 'err_msg': '删除失败！', 'info': response.json()}



	'''
	移动文件至指定目录
	0 删除成功；1 删除失败；
	'''
	def move(self, path, destination, newname=False):
		'''
		构造重命名的URL：https://pan.baidu.com/api/filemanager?
		bdstoken=  从首页可以获取到
		&opera=move  固定值
		&async=2  固定值
		&onnest=fail  固定值
		&channel=chunlei  固定在
		&web=1  固定值
		&app_id=250528  固定值
		&logid=MTU4MTk0MzY0MTQwNzAuNDA0MzQxOTM0MzE2MzM4Ng==  固定值
		&clienttype=0  固定值
		'''
		response = self.session.get('https://pan.baidu.com/', headers=self.headers)
		bdstoken = re.findall(r'initPrefetch\(\'(.+?)\'\,', response.content.decode("utf-8"))[0]
		url = 'https://pan.baidu.com/api/filemanager?bdstoken=%s&opera=move&async=2&onnest=fail&channel=chunlei&web=1&app_id=250528\
				&logid=MTU0ODU4MzUxMTgwNjAuNDg5NDkyMzg5NzAyMzY1MQ==&clienttype=0' % bdstoken
		if(not newname):
			newname = path.split('/')[-1]
		form_data = {"filelist": "[{\"path\":\"%s\",\"dest\":\"%s\",\"newname\":\"%s\"}]" % (path, destination, newname)}
		response = self.session.post(url, headers=self.headers, data=form_data)
		if(response.json()['errno'] == 0):
			return {'errno': 0, 'err_msg': '移动成功！'}
		else:
			return {'errno': 1, 'err_msg': '移动失败！', 'info': response.json()}


#pattern = 'yunData.SHARE_ID = "(.*?)"[\s\S]*yunData.SHARE_UK = "(.*?)"[\s\S]*yunData.FILEINFO = (.*?);[\s\S]*'


	'''
	随机生成4位字符串
	'''
	@staticmethod
	def generatePwd(n=4):
		pwd= ""
		for i in range(n):
			#print("i:",i)
			temp = random.randrange(0,3)
			#print("temp:",temp)
			if temp == 0:
				ch = chr(random.randrange(ord('A'),ord('Z') + 1))
				pwd += ch
			elif temp == 1:
				ch = chr(random.randrange(ord('a'),ord('z') + 1))
				pwd += ch
			else:
				pwd += str((random.randrange(0,10)))
		return pwd


	'''
	创建分享链接
	fid_list为列表，例如：[1110768251780445]
	0 创建成功；1 创建失败；
	'''
	def createShareLink(self, fid_list, period=0, pwd=False):
		'''
		构造重命名的URL：https://pan.baidu.com/share/set?
		bdstoken=  从首页可以获取到
		&channel=chunlei  固定在
		&web=1  固定值
		&app_id=250528  固定值
		&logid=MTU4MTk0MzY0MTQwNzAuNDA0MzQxOTM0MzE2MzM4Ng==  固定值
		&clienttype=0  固定值
		'''
		#response = self.session.get('https://pan.baidu.com/', headers=self.headers)
		bdstoken = self.bdstoken#re.findall(r'initPrefetch\(\'(.+?)\'\,', response.content.decode("utf-8"))[0]
		url = 'https://pan.baidu.com/share/set?bdstoken=%s&channel=chunlei&web=1&app_id=250528&dp-logid=%s&clienttype=0' % (self.bdstoken,self.dp_logid)
		print("createShareLink url:",url)
		print("input pwd:",pwd)
		if(not pwd):
			pwd = self.generatePwd()
		print("createShareLink pwd:",pwd)
		'''
		schannel=4  不知道什么意思，固定为4
		channel_list=[]  不知道什么意思，固定为[]
		period=0  0表示永久，7表示7天
		pwd=w4y5  分享链接的提取码，可自定义
		fid_list=[1110768251780445]  分享文件的id列表，可调用getFileList方法获取文件列表，包含fs_id
		'''
		form_data = {
			'schannel': 4,
			'channel_list': '[]',
			'period': period,
			'pwd': pwd,
			'eflag_disable': True,
			'fid_list': str(fid_list),
		}
		print("form_data:",form_data)
		response = self.session.post(url, headers=self.headers, data=form_data)
		print("response:",response)
		print("response:",response.json())
		if(response.json()['errno'] == 0):
			return {'errno': 0, 'err_msg': '创建分享链接成功！', 'info': {'link': response.json()['link'], 'pwd': pwd}}
		else:
			return {'errno': 1, 'err_msg': '创建分享链接失败！', 'info': response.json()}

	#def bdcreate(savepath, BDUSS, STOKEN, bdstoken):
	def bdcreate(self,savepath):
		# s.cookies['BDUSS'] = self.session.cookies['BDUSS']
		# s.cookies['STOKEN'] = self.session.cookies['STOKEN']
		self.headers = {
			'Host': 'pan.baidu.com',
			'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36',
		}
		#headers = {
		#'User-Agent': get_user_agent_pc(),
		#}
		# 创建文件夹
		create_floder = {
		# 不知道是什么，大部分情况为空
		'block_list': '[]',
		'isdir': '1',
		 # 保存的位置，创建文件夹
		'path': savepath
		}
		# 创建文件夹的链接
		url_create = 'https://pan.baidu.com/api/create?a=commit' \
		         '&channel=chunlei' \
		         '&web=1' \
		         '&app_id=250528' \
		         '&bdstoken=%s' \
		         '&dp-logid=%s' \
		         '&clienttype=0' % (self.bdstoken,self.dp_logid)
		#print("url_create:",url_create)
		response = self.session.post(url_create, data=create_floder, headers=self.headers)
		response.encoding = 'utf-8'
		#print(response.content)


	def parseUrlPwd(self):
		f = open('url_pwd.csv','r',encoding='utf-8');
		line = f.readline()
		all_url_pwd = [];
		while line:
			_url_pwd = [];
			#print("line content:",line)
			line_list = line.split(',')
			#print("line after split line_list:",line_list)
			if '提取码' not in line_list[1].strip():
				line = f.readline()
				continue
			#print('line_list 0',line_list[0])
			tiquma = line_list[1].strip().split('提取码')
			tiquma = tiquma[1].strip();
			title = line_list[2].strip();
			#print('line_list 1',tiquma[0:5].replace("：",""))
			_url_pwd.append(line_list[0])
			tiquma = tiquma[0:5].replace(":","")
			_url_pwd.append(tiquma.replace("：",""))
			_url_pwd.append(title)
			all_url_pwd.append(_url_pwd)
			line = f.readline()
		return all_url_pwd;

if __name__ == '__main__':

	ssl._create_default_https_context = ssl._create_unverified_context
	# url = 'http://www.baidu.com'  # 替换为你想访问的网址
	# response = requests.get(url)
	 
	# if response.status_code == 200:  # 请求成功
	#     print(response.text)  # 打印网页内容
	# else:
	#     print("Failed to retrieve the webpage: {response.status_code}")

	baidu = BaiDuPan();
	#print(baidu.generatePwd());

	newUrlPwd = open('newUrlPwd.csv','w',encoding='utf-8')
	errorUrlPwd = open('errorUrlPwd.csv','w',encoding='utf-8')
	errorCreateShareUrlPwd = open('errorCreateShareUrlPwd.csv','w',encoding='utf-8')
	verifyRet = baidu.verifyCookie();
	if verifyRet['errno'] != 0:
		print("verifyRet:",verifyRet['errno'],verifyRet['err_msg'])
		exit(1)
	else:
		print("verifyRet is 0")
	baidu.getFileList();

	parseVal = baidu.parseUrlPwd();
	#baidu.getSharePwd();
	#print("parseVal:",parseVal)
	#if len(parseVal) < 2 :
	for val in parseVal:
		#print("val 0",val[0])
		#print("val 1",val[1])
		print("val 2",val[2])
		newUrlPwd.write(val[0])
		newUrlPwd.write(',')
		newUrlPwd.write(val[1])
		newUrlPwd.write(',')
		dstPath = '/'+val[2];#"/创建测试" 要使用自己的目录,须加 '/' 同时 formdata里面 type 要去掉
		baidu.bdcreate('/202408/'+val[2]);
		retValue = baidu.saveShare(str(val[0]),str(val[1]),'/202408/'+val[2]);
		print("save result:",retValue)
		if('error' in retValue[1]):
			print("save result error:",retValue)
			errorUrlPwd.write(val[0])
			errorUrlPwd.write(',')
			errorUrlPwd.write(val[1])
			errorUrlPwd.write(',')
			errorUrlPwd.write(val[2])
			errorUrlPwd.write('\n')
			deleteRet = baidu.delete('/202408/'+val[2]);
			print("deleteRet:",deleteRet)
			continue;
		files = baidu.getFileList();
		#print("files",files)
		#print("files type",type(files))
		#filesJson = json.loads(files);
		# print("filesJson:",filesJson)
		# #print("files:",files.loads(files));['server_filename'];
		save_fs_id = '';
		for k,v in files.items():
			#print("item k:",k)
			#print("item v:",v)
			if type(v) is list:
				for k1 in v:
					#print("k1:",k1)
					#print("dstPath is",dstPath)
					#print("type is",type(k1))
					#if any('测试' in kk for kk in k1.values()):
						#print("k1:",k1)
						#print(json.dumps(k1, ensure_ascii=False))
					if dstPath in json.dumps(k1, ensure_ascii=False):
						#print("xx k1:",k1)
						for k2 in k1:
							#print("11 k2:",k2)
							if 'fs_id' == k2:
								#print("22 k2:",k2)
								#print("k2 v2:",k1[k2])
								save_fs_id = k1[k2]
		createLinkRet = baidu.createShareLink('['+str(save_fs_id)+']');
		
		if createLinkRet['errno'] != 0:
			print("createLinkRet error:",createLinkRet)
			errorCreateShareUrlPwd.write(val[0])
			errorCreateShareUrlPwd.write(',')
			errorCreateShareUrlPwd.write(val[1])
			errorCreateShareUrlPwd.write(',')
			errorCreateShareUrlPwd.write(val[2])
			errorCreateShareUrlPwd.write('\n')
			continue;
		#print("createLinkRet:",createLinkRet)

		if createLinkRet['info']['link']:
			print("link:",createLinkRet['info']['link'])
			newUrlPwd.write(createLinkRet['info']['link'])
		newUrlPwd.write(',')

		if createLinkRet['info']['pwd']:
			print("pwd:",createLinkRet['info']['pwd'])
			newUrlPwd.write(createLinkRet['info']['pwd'])
		newUrlPwd.write(',')
		newUrlPwd.write(val[2])
		newUrlPwd.write('\n')
		#break
	newUrlPwd.close()
	errorUrlPwd.close()
	errorCreateShareUrlPwd.close()
	'''
	 info ={
                    "0":"转存成功。",
                    "-1":"由于您分享了违反相关法律法规的文件，分享功能已被禁用，之前分享出去的文件不受影响。",
                    "-2":"用户不存在,请刷新页面后重试。",
                    "-3":"文件不存在,请刷新页面后重试。",
                    "-4":"登录信息有误，请重新登录试试。",
                    "-5":"host_key和user_key无效。",
                    "-6":"请重新登录。",
                    "-7":"该分享已删除或已取消。",
                    "-8":"该分享已经过期。",
                    "-9":"访问密码错误。",
                    "-10":"分享外链已经达到最大上限100000条，不能再次分享。",
                    "-11":"验证cookie无效。",
                    "-14":"对不起，短信分享每天限制20条，你今天已经分享完，请明天再来分享吧！",
                    "-15":"对不起，邮件分享每天限制20封，你今天已经分享完，请明天再来分享吧！",
                    "-16":"对不起，该文件已经限制分享！",
                    "-17":"文件分享超过限制。",
                    "-21":"预置文件无法进行相关操作。",
                    "-30":"文件已存在。",
                    "-31":"文件保存失败。",
                    "-33":"一次支持操作999个，减点试试吧。",
                    "-32":"未知结果。",
                    "-70":"你分享的文件中包含病毒或疑似病毒，为了你和他人的数据安全，换个文件分享吧。",
                    "2":"参数错误。",
                    "3":"未登录或帐号无效。",
                    "4":"存储好像出问题了，请稍候再试。",
                    "108":"文件名有敏感词，优化一下吧。",
                    "110":"分享次数超出限制，可以到“我的分享”中查看已分享的文件链接。",
                    "114":"当前任务不存在，保存失败。",
                    "115":"该文件禁止分享。",
                    "112":'页面已过期，请刷新后重试。',
                    "9100":'你的帐号存在违规行为，已被冻结。',
                    "9200":'你的帐号存在违规行为，已被冻结。',
                    "9300":'你的帐号存在违规行为，该功能暂被冻结。',
                    "9400":'你的帐号异常，需验证后才能使用该功能。',
                    "9500":'你的帐号存在安全风险，已进入保护模式，请修改密码后使用。'}
	'''